import { _decorator, Component, Node } from 'cc';
import { GGResource } from '../../../framework/core/base/GGResource';
import { JsonAsset } from 'cc';
import { Prefab } from 'cc';
import { instantiate } from 'cc';
import { Vec3 } from 'cc';
import { AnimType, BrickAnimInfo, BrickCleanAnim, PointInfo } from '../../../utils/Types';
import { Brick } from './Brick';
import { EVENT_NAMES } from '../../../utils/Enums';
import { Vec2 } from 'cc';
import Config from '../../../utils/Config';
import DataMgr from '../../../utils/DataMgr';
import { AnimCtrl } from './AnimCtrl';
import { Quat } from 'cc';
import { tween } from 'cc';
import Design from '../../../utils/Design';
import { DragMove } from '../../../ui/operate/src/scripts/DragMove';
import { RandomUtil } from '../../../common/src/util/RandomUtil';
import { AudioManager } from '../../../common/src/manager/AudioManager';
const { ccclass, property } = _decorator;

@ccclass('BricksCtrl')
export class BricksCtrl extends Component {
    @property( {type: Node, displayName: "地板定位" } )
    floorNode: Node = null;
    
    @property( {type: Prefab, displayName: "地砖预制体" } )
    tilePre: Prefab = null;
    
    @property( {type: Prefab, displayName: "六边形块预制体" } )
    brickPre: Prefab = null;
    
    // 关卡配置
    private targetJson:JsonAsset = null
    private grids = []

    // 动画管理器
    private animCtrl: AnimCtrl = null
    // 检查链条
    private checkTowerList: Vec2[] = []
    // 动画标记
    private animTag = false
    // 计数相关
    // 最大的数量
    private maxCount: number = 0
    // 当前的数量
    private currentCount: number = 0
    // 当前条件的块数量
    private addCount: number = 0

    start() {
        this.initListener()
        this.initValues()
    }

    protected update(dt: number): void {
        if (this.animTag == false) {
            if (this.checkTowerList.length > 0) {
                const pos = this.checkTowerList.splice(0, 1)[0]
                this.animTag = true
                const value = this.grids[pos.x][pos.y]

                // 获取相邻的塔
                const closees = this.getRimTower(pos.x, pos.y)
                this.cleanBricks(value, closees)
            }
        }
    }

    protected onDestroy(): void {
        gg.systemEvent.off(EVENT_NAMES.BRICK_FLY_END, this.brickFlyEnd, this)
        gg.systemEvent.off(EVENT_NAMES.BRICK_CLEAN_END, this.brickCleanEnd, this)
        gg.systemEvent.off(EVENT_NAMES.DRAG_RECEIVE_COLOR, this.getDragBricks, this)
    }
    
    // ---------------------- 初始化 ---------------------- //
    private initListener() {
        gg.systemEvent.on(EVENT_NAMES.BRICK_FLY_END, this.brickFlyEnd, this)
        gg.systemEvent.on(EVENT_NAMES.BRICK_CLEAN_END, this.brickCleanEnd, this)
        gg.systemEvent.on(EVENT_NAMES.DRAG_RECEIVE_COLOR, this.getDragBricks, this)
    }

    private initValues() {
        this.animCtrl = this.getComponent(AnimCtrl)
    }

    // ---------------------- 外部方法 ---------------------- //
    // 新游戏
    public onNewGame(ja: JsonAsset) {
        this.targetJson = ja
        this.grids = this.targetJson.json["grids"]

        this.maxCount = 0
        this.currentCount = 0

        this.refreshGround()
    }

    // 点击砖块的操作
    public onBrickClicked(brick: Brick) {
        if (DataMgr.isUsingHammer) {
            // 清除选中的块所在列和选中块颜色一样的所有块
            const info = this.grids[brick.x][brick.z]
            const tower = this.floorNode.getChildByName(brick.x + "_" + brick.z)

            // 选中的颜色
            const selColor = brick.color

            // 清理数值
            for (var i = (info.blocks.length - 1); i >= 0; i--) {
                if (selColor == info.blocks[i]) {
                    info.blocks.splice(i, 1)
                }
            }

            // 清理对应块
            for (var i = (tower.children.length - 1); i >= 0; i--) {
                const brickCom = tower.children[i].getComponent(Brick)
                if (brickCom != null) {
                    if (brickCom.color == selColor) {
                        brickCom.node.removeFromParent()
                    }
                }
            }

            // 对齐
            for (var i = (info.blocks.length - 1); i >= 0; i--) {
                const brickNode = tower.children[i + 1]
                brickNode.setPosition(0, i * Design.brickConfig.brickSpace, 0)
            }

            // DataMgr.isUsingHammer = false
            gg.systemEvent.emit(EVENT_NAMES.SET_CLICKED_BRECK_REMIND, false)
            AudioManager.playSound("audio:common/炸弹音效");
        } else {
            const info = this.grids[brick.x][brick.z]
            console.log (info)
        }
    }

    // 往一个塔添加六边形块
    public pushBrickToTower(x: number, z: number, colors: number[]) {
        
        this.addCount = this.addCount + colors.length

        const tileNode = this.floorNode.getChildByName(x + "_" + z)
        const value = this.grids[x][z]

        for (var i = 0; i < colors.length; i++) {
            value.blocks.push(colors[i])

            const brickNode = instantiate(this.brickPre)
            brickNode.parent = tileNode
            brickNode.setPosition(0, (value.blocks.length) * Design.brickConfig.brickSpace, 0)
            brickNode.getComponent(Brick).color = colors[i]
            brickNode.getComponent(Brick).setLoc(x, z)
            brickNode.getComponent(Brick).isBase = false
            brickNode.name = "六边形_" + colors[i]
        }

        this.checkTowerList.unshift(new Vec2(x, z))
    }

    // 获取指定位置的所有六边形块
    public getBricksAt(x: number, z: number) {
        return this.floorNode.getChildByName(x + "_" + z)
    }

    // 重置某列的位置
    public resetColumnAt(columnNode: Node) {
        const arr = columnNode.name.split("_")
        const ix = parseInt( arr[0] )
        const iz = parseInt( arr[1] )
        
        columnNode.setPosition(this.getPosAt(ix, iz))
    }

    // 将某一个对象和另一个对象的位置进行交换
    public exchangeColumn(selColumn: Node, moveColumn: Node, ctrlValue: boolean = false) {
        // 选中的信息
        const selArr = selColumn.name.split("_")
        const selX = parseInt( selArr[0] )
        const selZ = parseInt( selArr[1] )
        
        const selPos = this.getPosAt(selX, selZ)

        // 移动的信息
        const moveArr = moveColumn.name.split("_")
        const moveX = parseInt( moveArr[0] )
        const moveZ = parseInt( moveArr[1] )
        
        const movePos = this.getPosAt(moveX, moveZ)
        
        // 交换
        selColumn.position = movePos.clone()
        moveColumn.position = selPos.clone()

        if (ctrlValue == true) {
            // 数据交换
            const tempName = selColumn.name
            selColumn.name = moveColumn.name
            moveColumn.name = tempName

            const tempGrid = this.grids[selX][selZ]
            this.grids[selX][selZ] = this.grids[moveX][moveZ]
            this.grids[moveX][moveZ] = tempGrid

            // 调整定位
            this.grids[selX][selZ].x = selX
            this.grids[selX][selZ].z = selZ
            
            this.grids[moveX][moveZ].x = moveX
            this.grids[moveX][moveZ].z = moveZ

            // 更新子节点下面的块的定位信息
            for (var i = 0; i < selColumn.children.length; i++) {
                const blockCom = selColumn.children[i].getComponent(Brick)
                if (blockCom) {
                    blockCom.x = moveX
                    blockCom.z = moveZ
                }
            }

            for (var i = 0; i < moveColumn.children.length; i++) {
                const blockCom = moveColumn.children[i].getComponent(Brick)
                if (blockCom) {
                    blockCom.x = selX
                    blockCom.z = selZ
                }
            }
        }
    }

    // ---------------------- 内部方法 ---------------------- //
    // 刷新地面
    private refreshGround() {
        this.floorNode.removeAllChildren()

        for (var ix = 0; ix < this.grids.length; ix++) {
            for (var iz = 0; iz < this.grids[ix].length; iz++) {
                const value = this.grids[ix][iz]
                if (value.isOpened) {
                    const posX = ix * Design.panelWidth - 0.5 * (this.grids.length - 1) * Design.panelWidth +  ((iz % 2 != 0) ? Design.panelWidth / 2 : 0 )
                    const posZ = iz * Design.panelHeight - 0.5 * (this.grids[ix].length - 1) * Design.panelHeight
    
                    const tileNode = instantiate( this.tilePre )
                    tileNode.setPosition(posX, 0, posZ)
                    tileNode.parent = this.floorNode
                    tileNode.name = ix + "_" + iz
                    tileNode.getComponent(Brick).x = ix
                    tileNode.getComponent(Brick).z = iz
                    tileNode.getComponent(Brick).isBase = true
    
                    this.addBrickAt(tileNode, value)
                }
            }
        }

        console.log ("总量 = " + this.maxCount)
    }

    // 清除指定塔的块
    private cleanBricks(value: PointInfo, closees: PointInfo[]) {
        // 保证数量大于0，防止出现 null == null 的情况
        if (value.blocks.length > 0) {
            for (var i = 0; i < closees.length; i++) {
                const close = closees[i]
                if (close.blocks.length > 0) {
                    if (value.blocks[value.blocks.length - 1] == close.blocks[close.blocks.length - 1]) {
                        this.moveBlockTo(value, close)
                        return
                    }
                }
            }
        }

        // 再判断当前的是否需要清理

        this.cleanTowerAt(value.x, value.z)
        this.animTag = false
    }

    // 将一个塔的六边形块移动到另一个塔中
    private moveBlockTo(source: PointInfo, target: PointInfo) {
        const flyBricks:BrickAnimInfo[] = []
        for (var i = (source.blocks.length - 1); i >= 0; i--) {
            if (target.blocks[target.blocks.length - 1] == source.blocks[source.blocks.length - 1]) {
                const value = source.blocks.splice(i, 1)
                target.blocks.push(value[0])
    
                const sourceTower = this.floorNode.getChildByName(source.x + "_" + source.z)
                const targetTower = this.floorNode.getChildByName(target.x + "_" + target.z)
    
                const lastBrick = sourceTower.children[sourceTower.children.length - 1]
                lastBrick.getComponent(Brick).x = target.x
                lastBrick.getComponent(Brick).z = target.z

                const worldPosition = new Vec3()
                lastBrick.getWorldPosition(worldPosition)
                lastBrick.parent = targetTower
                lastBrick.setWorldPosition(worldPosition)
                
                const info  = new BrickAnimInfo()
                info.brick = lastBrick
                info.end = new Vec3(0, (target.blocks.length - 1) * Design.brickConfig.brickSpace, 0)

                flyBricks.push(info)
            }
        }

        if (flyBricks.length > 0) {
            const anim = { type: AnimType.BRICKFLY,
                infos: flyBricks,
                dir: Config.getDir(source.x, source.z, target.x, target.z),
                originX: source.x, originZ: source.z,
                endX: target.x, endZ: target.z }
            this.animCtrl.insertAnim(anim)
        }
    }

    // 在一个塔的位置，放置六边形块
    private addBrickAt(tileNode: Node, info: PointInfo) {
        const arr = tileNode.name.split("_")
        const x = parseInt( arr[0] )
        const z = parseInt( arr[1] )

        for (var i = 0; i < info.blocks.length; i++) {
            const brickNode = instantiate(this.brickPre)
            brickNode.parent = tileNode
            brickNode.setPosition(0, (i + 1) * Design.brickConfig.brickSpace , 0)
            brickNode.getComponent(Brick).color = info.blocks[i]
            brickNode.getComponent(Brick).setLoc(x, z)
            brickNode.getComponent(Brick).isBase = true
            brickNode.name = "六边形_" + info.blocks[i]

            this.maxCount++
            this.currentCount++
        }
    }
    
    // 选择一个塔的位置，获取其六边的塔
    private getRimTower(x: number, z: number) {
        const closees = []
        var dirs = []
        if (z % 2 != 0) {
            // 凹进去的
            dirs = [new Vec2(1, 0), new Vec2(-1, 0), new Vec2(0, 1), new Vec2(0, -1), new Vec2(1, -1), new Vec2(1, 1)]
        } else {
            dirs = [new Vec2(1, 0), new Vec2(-1, 0), new Vec2(0, 1), new Vec2(0, -1), new Vec2(-1, -1), new Vec2(-1, 1)]
        }

        for (var i = 0; i < dirs.length; i++) {
            const newDir = new Vec2(x + dirs[i].x, z + dirs[i].y)

            if (this.checkInArea(newDir.x, newDir.y)) {
                closees.push(this.grids[newDir.x][newDir.y])
            }
        }

        return closees
    }

    // 检查周围的块中是否有可以
    private checkHasSame(x: number, z: number) {
        const value = this.grids[x][z]
        // 获取相邻的塔
        const closees = this.getRimTower(x, z)

        var hasSame = false
        if (value.blocks.length > 0) {
            for (var i = 0; i < closees.length; i++) {
                const close = closees[i]
                if (close.blocks.length > 0) {
                    if (value.blocks[value.blocks.length - 1] == close.blocks[close.blocks.length - 1]) {
                        hasSame = true
                    }
                }
            }
        }

        return hasSame
    }

    // 判断一个位置是否超出显示
    private checkInArea(x: number, z: number) {
        if (x >= 0 && x < this.grids.length) {
            if (z >= 0 && z < this.grids[x].length) {
                return true
            }
        }

        return false
    }

    // 清理掉顶部的六边形块
    private cleanSameAt(targetX: number, targetZ: number, count: number) {
        // 清理数值
        const gridInfo = this.grids[targetX][targetZ]
        gridInfo.blocks.splice(gridInfo.blocks.length - count, count)

        const tileNode = this.floorNode.getChildByName(targetX + "_" + targetZ)
        const bricks = []
        for (var i = 0; i < count; i++) {
            const brickNode = tileNode.children[tileNode.children.length - 1 - i]
            bricks.push(brickNode)
        }

        const anim = { type: AnimType.BRICKCLEAN, 
            bricks: bricks, 
            x: targetX, 
            z: targetZ }
        this.animCtrl.insertAnim(anim)
    }

    // 根据定位获取坐标
    private getPosAt(ix: number, iz: number): Vec3 {

        const posX = ix * Design.panelWidth - 0.5 * (this.grids.length - 1) * Design.panelWidth +  ((iz % 2 != 0) ? Design.panelWidth / 2 : 0 )
        const posZ = iz * Design.panelHeight - 0.5 * (this.grids[ix].length - 1) * Design.panelHeight

        return new Vec3(posX, 0, posZ)
    }

    // 获取基础块的数量
    private getBaseCount() {
        var allCount = 0
        this.floorNode.children.forEach(element => {
            for (var i = 0; i < element.children.length; i++) {
                const brickCom = element.children[i].getComponent(Brick)
                if (brickCom) {
                    if (brickCom.isBase == true) {
                        allCount++
                    }
                }
            }
        });

        return allCount
    }

    // ---------------------- 事件 ---------------------- //
    // 六边形块飞行结束
    private brickFlyEnd(originPos: Vec2, targetPos: Vec2) {
        const originInfo = this.grids[originPos.x][originPos.y]

        this.animTag = false

        // 首先检测周围是否有可以放置的，之后再判断是否需要清理
        if (this.checkHasSame(targetPos.x, targetPos.y)) {
            this.pushBrickToTower(targetPos.x, targetPos.y, [])
            this.checkTowerList.push(new Vec2(originPos.x, originPos.y))
        } else {
            this.cleanTowerAt(targetPos.x, targetPos.y)
        }
    }

    // 清理指定位置的积木
    private cleanTowerAt(x: number, z: number) {
        const endInfo = this.grids[x][z]
        var count = 0
        for (var i = (endInfo.blocks.length - 1); i >= 0; i--) {
            if (endInfo.blocks[endInfo.blocks.length - 1] == endInfo.blocks[i]) {
                count++
            } else {
                break
            }
        }

        if (count >= 10) {
            this.cleanSameAt(x, z, count)
        }
    }

    // 六边形清理动画结束
    private brickCleanEnd(anim: BrickCleanAnim) {
        // var allCount = 0
        
        // for (var ix = 0; ix < this.grids.length; ix++) {
        //     for (var iz = 0; iz < this.grids[ix].length; iz++) {
        //         const value = this.grids[ix][iz]
        //         allCount += value.blocks.length
        //     }
        // }

        // if (this.grids[anim.x][anim.z].blocks.length > 0) {
        //     this.checkTowerList.push(new Vec2(anim.x, anim.z))
        // }

        // if (allCount <= 0) {
        //     gg.systemEvent.emit(EVENT_NAMES.ON_GAME_END, true)
        // }

        // if (this.addCount > anim.bricks.length)

        this.currentCount = this.getBaseCount()

        console.log ("剩余数量 = " + this.currentCount)

        if (this.currentCount <= 0) {
            gg.systemEvent.emit(EVENT_NAMES.ON_GAME_END, true)
        }
    }

    // 获取到拖拽块
    private getDragBricks(dragItem: DragMove) {
        // 首先获取最上层的颜色
        const topArr = []
        const allArr = []

        const copyDrags = []
        console.log (Config.dragColorArray)
        // 再清理包含在底部块中的
        for (var i = 0; i < Config.dragColorArray.length; i++) {
            if (Config.dragColorArray[i] != -1) {
                copyDrags.push(Config.dragColorArray[i])
            }
        }

        for (var ix = 0; ix < this.grids.length; ix++) {
            for (var iz = 0; iz < this.grids[ix].length; iz++) {
                const value = this.grids[ix][iz]
                if (value.blocks.length > 0) {
                    const topValue = value.blocks[value.blocks.length - 1]
                    var isClean = false
                    for (var i = 0; i < copyDrags.length; i++) {
                        if (isClean == false) {
                            if (topValue == copyDrags[i] ) {
                                isClean = true
                                copyDrags[i] = -1
                            }
                        }
                    }

                    console.log ("顶 = " + topValue)
                    if (isClean == false)
                        topArr.push(topValue)
                    for (var i = 0; i < value.blocks.length; i++) {
                        allArr.push(value.blocks[i])
                    }
                }
            }
        }

        
        console.log ("顶部颜色 = ")
        console.log (topArr)

        const per = 100 - (this.currentCount / this.maxCount * 100)
        const curLev = Config.getCurrentLevel()

        // 获取到要操作的范围
        const fanwei = curLev["fanwei"].split(",")
        var loc = 0
        for (var i = 0; i < (fanwei.length - 1); i++) {
            const pre = parseInt(fanwei[i])
            const next = parseInt(fanwei[i + 1])
            if (per >= pre && per <= next) {
                loc = i
                break
            }
        }

        const probability = curLev["probability" + (loc + 1)].split(",")
        const randomCount = Math.random()

        var allValue = 0
        var countIndex = 0
        for (var i = 0; i < probability.length; i++) {
            allValue += parseFloat(probability[i])
            if (randomCount <= allValue) {
                countIndex = i + 1
                break
            }
        }

        const resultArr = []

        if (countIndex == 1) {
            resultArr.push(topArr[Math.floor(Math.random() * topArr.length)])
        } else if (countIndex == 2) {
            resultArr.push(allArr[Math.floor(Math.random() * allArr.length)])
            newArr = []
            for (var i = 0; i < topArr.length; i++) {
                if (topArr[i] != resultArr[0] && topArr[i] != resultArr[1]) {
                    newArr.push(topArr[i])
                }
            }
            resultArr.push(newArr[Math.floor(Math.random() * newArr.length)])
        } else if (countIndex == 3) {
            resultArr.push(allArr[Math.floor(Math.random() * allArr.length)])

            var newArr = []
            for (var i = 0; i < allArr.length; i++) {
                if (allArr[i] != resultArr[0]) {
                    newArr.push(allArr[i])
                }
            }

            resultArr.push(newArr[Math.floor(Math.random() * newArr.length)])

            newArr = []
            for (var i = 0; i < topArr.length; i++) {
                if (topArr[i] != resultArr[0] && topArr[i] != resultArr[1]) {
                    newArr.push(topArr[i])
                }
            }
            resultArr.push(newArr[Math.floor(Math.random() * newArr.length)])
        }

        console.log ("结果 = ")
        console.log (resultArr)

        const colorsArr = []
        if (countIndex == 1) {
            const count = RandomUtil.randomInteger(3, 6)
            for (var i = 0; i < count; i++) {
                colorsArr.push(resultArr[0])
            }
        } else if (countIndex == 2) {
            for (var i = 0 ; i < resultArr.length; i++) {
                const count = RandomUtil.randomInteger(3, 4)
                for (var j = 0; j < count; j++) {
                    colorsArr.push(resultArr[i])
                }
            }
        } else if (countIndex == 3) {
            for (var i = 0 ; i < resultArr.length; i++) {
                const count = RandomUtil.randomInteger(1, 3)
                for (var j = 0; j < count; j++) {
                    colorsArr.push(resultArr[i])
                }
            }
        }

        dragItem.colors = colorsArr
    }
}


